#include "configdevicedlg.h"
#include "ui_configdevicedlg.h"
#include <QDebug>
#include "common.h"
#include "serialportsetdlg.h"
#include <QMessageBox>
#include <QProgressDialog>
#include "projectdatabaseoperations.h"

#define MAX_DATA_LEN 255

extern QSerialPort* serial;
static uchar devicePAByteHigh;
static uchar devicePAByteLow;
static QString PAStr;

ConfigDeviceDlg::ConfigDeviceDlg(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ConfigDeviceDlg)
{
    ui->setupUi(this);
    
    knxSerial = new QknxSerial;
    error = new ErrorToDo;
    
    connect(ui->searchSNByPAlineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateSearchSNByPABtn(QString))); 
    connect(ui->inputSNlineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateSearchDeviceBySNBtn(QString)));
    connect(ui->SNComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateSearchDeviceBySNBtn(QString)));
    connect(ui->showPAlineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateDownloadPAAndDataBtn(QString)));
    connect(ui->inputPADownloadlineEdit, SIGNAL(textChanged(QString)), this, SLOT(updateDownloadPAAndDataBtn(QString)));
    connect(ui->onecheckBox, SIGNAL(toggled(bool)), this, SLOT(selectSearchMethodOne(bool)));
    connect(ui->twocheckBox, SIGNAL(toggled(bool)), this, SLOT(selectSearchMethodTwo(bool)));
    
    connect(ui->readProModePABtn, SIGNAL(clicked(bool)), this, SLOT(readPAWhenDeviceProMode()));
    connect(ui->searchSNByPABtn, SIGNAL(clicked(bool)), this, SLOT(searchSNByPA()));
    connect(ui->searchSNWhenPAFFBtn, SIGNAL(clicked(bool)), this, SLOT(searchSNWhenPAFF()));
    connect(ui->searchDeviceBySNBtn, SIGNAL(clicked(bool)), this, SLOT(searchDeviceBySN()));
    connect(ui->downloadPABtn, SIGNAL(clicked(bool)), this, SLOT(downloadPA()));
    connect(ui->downloadDataBtn, SIGNAL(clicked(bool)), this, SLOT(downloadData()));
}

ConfigDeviceDlg::~ConfigDeviceDlg()
{
    delete knxSerial;
    delete error;
    delete ui;
}

void ConfigDeviceDlg::selectSearchMethodOne(bool checked)
{
    if(checked)
    {
        ui->twocheckBox->setCheckState(Qt::Unchecked);
    }
}

void ConfigDeviceDlg::selectSearchMethodTwo(bool checked)
{
    if(checked)
    {
        ui->onecheckBox->setCheckState(Qt::Unchecked);
    }
}

void ConfigDeviceDlg::updateSearchSNByPABtn(const QString &text)
{
    QRegExp exp("^[0-9]+\\.[0-9]+\\.[0-9]+$");  //注意QString里面'\'要用'\\'表示，实际上正则'\.'就代表了'.'
    if(!text.contains(exp))
        ui->searchSNByPABtn->setEnabled(false);
    else
        ui->searchSNByPABtn->setEnabled(true);
}

void ConfigDeviceDlg::updateSearchDeviceBySNBtn(const QString &text)
{
    if(text.isEmpty() && ui->inputSNlineEdit->text().isEmpty())
        ui->searchDeviceBySNBtn->setEnabled(false);
    else
    {
        ui->inputSNlineEdit->setText(ui->SNComboBox->currentText());
        ui->searchDeviceBySNBtn->setEnabled(true);
    }
}

void ConfigDeviceDlg::updateDownloadPAAndDataBtn(const QString &text)
{
    QRegExp exp("^[0-9]+\\.[0-9]+\\.[0-9]+$");
    if(!text.contains(exp))
    {
        ui->downloadPABtn->setEnabled(false);
        ui->downloadDataBtn->setEnabled(false);
    }
    else
    {
        //计算物理地址
        int mainPA = text.section('.', 0, 0).toInt();
        if(mainPA < 0 || mainPA > 15)
        {
            qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址第一段范围0-15";
            error->showWarningMsg(this, "物理地址第一段范围0-15");
            return;
        }
        int middlePA = text.section('.', 1, 1).toInt();
        if(middlePA < 0 || middlePA > 15)
        {
            qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址第二段范围0-15";
            error->showWarningMsg(this, "物理地址第二段范围0-15");
            return;
        }
        int lastPA = text.section('.', 2, 2).toInt();
        if(lastPA < 0 || lastPA > 255)
        {
            qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址第三段范围0-255";
            error->showWarningMsg(this, "物理地址第三段范围0-255");
            return;
        }
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址三段："<<mainPA<<middlePA<<lastPA;
        devicePAByteHigh = mainPA*16 + middlePA;
        devicePAByteLow = lastPA;
        PAStr = text;
        
        ui->downloadPABtn->setEnabled(true);
        ui->downloadDataBtn->setEnabled(true);
    }
}

void ConfigDeviceDlg::searchSNByPA()
{   
    QString text = ui->searchSNByPAlineEdit->text();
    int mainPA = text.section('.', 0, 0).toInt();
    if(mainPA < 0 || mainPA > 15)
    {
        qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址第一段范围0-15";
        error->showWarningMsg(this, "物理地址第一段范围0-15");
        return;
    }
    int middlePA = text.section('.', 1, 1).toInt();
    if(middlePA < 0 || middlePA > 15)
    {
        qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址第二段范围0-15";
        error->showWarningMsg(this, "物理地址第二段范围0-15");
        return;
    }
    int lastPA = text.section('.', 2, 2).toInt();
    if(lastPA < 0 || lastPA > 255)
    {
        qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址第三段范围0-255";
        error->showWarningMsg(this, "物理地址第三段范围0-255");
        return;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址三段："<<mainPA<<middlePA<<lastPA;
    devicePAByteHigh = mainPA*16 + middlePA;
    devicePAByteLow = lastPA;
    PAStr = text;
    
    //形成knx报文并发送获取序列号
    uchar getSNMessage[19] = {0x00};
    uchar propertyID = 0x0B;
    
    uchar deviceTypeHigh = 0xFF;
    uchar deviceTypeLow = 0xFF;
    
    knxSerial->knxGetSNMessage(getSNMessage, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, propertyID, deviceTypeHigh, deviceTypeLow);
    uchar snBuff[64][6] = {{0}};
    int deviceNum = knxSerial->knxSearchDeviceSN(serial, getSNMessage, 19, MC_PA_BYTE1, MC_PA_BYTE2, snBuff, propertyID);
    if(deviceNum <= 0)
    {
        qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"未搜索到序列号";
        error->showWarningMsg(this, "未搜索到序列号");
        return;
    }
    
    //转换序列号类型并显示
    QString sn;
    sn = knxSerial->knxSNUcharToString(sn, snBuff[0]);
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"sn:"<<sn;
    ui->SNComboBox->clear();
    ui->SNComboBox->addItem(sn);
}

void ConfigDeviceDlg::searchSNWhenPAFF()
{
    devicePAByteHigh = 0xFF;
    devicePAByteLow = 0xFF;
    
    ui->SNComboBox->clear();
    //形成knx报文并发送获取序列号
    uchar getSNMessage[19] = {0x00};
    
    uchar propertyID = 0x0C;
    uchar deviceTypeHigh = 0xFF;
    uchar deviceTypeLow = 0xFF;
    knxSerial->knxGetSNMessage(getSNMessage, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, propertyID, deviceTypeHigh, deviceTypeLow);
    uchar snBuff[10][6] = {{0}};  //设置最多10个
    if(!serial->isOpen())
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"串口未打开";
        error->showCriticalMsg(this, "knx串口未打开");
        return;
    }
    int deviceNum = knxSerial->knxSearchDeviceSN(serial, getSNMessage, 19, MC_PA_BYTE1, MC_PA_BYTE2, snBuff, propertyID);
    if(deviceNum <= 0)
    {
        qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"未搜索到序列号";
        error->showWarningMsg(this, "未搜索到序列号");
        return;
    }
    
    //转换序列号类型并显示
    QString sn;
    for(int i = 0;i < deviceNum; i++)
    {
        sn = knxSerial->knxSNUcharToString(sn, snBuff[i]);
        qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"sn:"<<sn;
        ui->SNComboBox->addItem(sn);
    }
}

//搜索设备通过序列号，其实只是设置其处于编程模式
void ConfigDeviceDlg::searchDeviceBySN()
{
    QString snStr;
    //获取序列号并转换为uchar
    snStr = ui->inputSNlineEdit->text();
    uchar snUchar[6] = {0x00};
    if(knxSerial->knxSNQStringToUchar(snUchar, snStr) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取转换的uchar型设备序列号失败";
        error->showCriticalMsg(this, "获取转换的uchar型设备序列号失败");
        return ;
    }
    
    //获取报文并发送报文设置该设备处于编程模式
    uchar setDeviceModeMessage[22] = {0x00};
    knxSerial->knxGetDeviceModeMessage(setDeviceModeMessage, snUchar, MC_PA_BYTE1, MC_PA_BYTE2, 1);
    int res = knxSerial->knxSetDeviceMode(serial, setDeviceModeMessage, 22);
    if(res < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设置编程模式失败";
        error->showCriticalMsg(this, "设置编程模式失败，请确认总线连接正常后重试，仍无法解决请联系管理员");
        return;
    }
    qInfo()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"搜索设备成功，可进行物理地址及配置数据下载";
    error->showInfoMsg(this, "搜索设备成功，可进行物理地址及配置数据下载");
}

//根据序列号写物理地址
void ConfigDeviceDlg::downloadPABySN()
{
    QString snStr;
    //获取序列号并转换为uchar数组
    snStr = ui->inputSNlineEdit->text();
    uchar snUchar[6] = {0x00};
    if(knxSerial->knxSNQStringToUchar(snUchar, snStr) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取转换的uchar型设备序列号失败";
        error->showCriticalMsg(this, "获取转换的uchar型设备序列号失败");
        return ;
    }
    
    //进行点对点连接判断物理地址是否已存在
    uchar connectDeviceMessage[14] = {0x00};
    knxSerial->knxGetConOrDisMessage(connectDeviceMessage, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, 0);
    uchar disConnectMessage[14] = {0x00};
    knxSerial->knxGetConOrDisMessage(disConnectMessage, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, 1);
    int res = knxSerial->knxConnectOrDisconnect(serial, connectDeviceMessage, 14);
    if(!res)
    {
        qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接成功，物理地址已分配";
        error->showWarningMsg(this, "点对点连接成功，物理地址已分配");
        knxSerial->knxConnectOrDisconnect(serial, disConnectMessage, 14);
        return;
    }
    
    //根据序列号写物理地址
    uchar devicePAWriteMessage[27] = {0x00};
    knxSerial->knxGetWritePAMessage(devicePAWriteMessage, snUchar, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow);
    if(knxSerial->knxWritePAAccordingToSN(serial, devicePAWriteMessage, 27) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址写入失败";
        error->showCriticalMsg(this, "物理地址写入失败");
        return ;
    }
    
    //进行点对点连接判断物理地址是否写入成功
    res = knxSerial->knxConnectOrDisconnect(serial, connectDeviceMessage, 14);
    if(res < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接不成功，物理地址写入失败";
        error->showCriticalMsg(this, "点对点连接不成功，物理地址写入失败");
        return ;
    }
    
    qInfo()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接成功，物理地址写入成功";
    error->showInfoMsg(this, "点对点连接成功，物理地址写入成功");
    
    //断开点对点连接
    knxSerial->knxConnectOrDisconnect(serial, disConnectMessage, 14);
}

//对处于编程模式的设备进行物理地址下载
void ConfigDeviceDlg::downloadPAWhenProMode()
{
    //进行点对点连接判断物理地址是否已存在
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"物理地址："<<PAStr;
    uchar connectDeviceMessage[14] = {0x00};
    knxSerial->knxGetConOrDisMessage(connectDeviceMessage, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, 0);
    uchar disConnectMessage[14] = {0x00};
    knxSerial->knxGetConOrDisMessage(disConnectMessage, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, 1);
    int res = knxSerial->knxConnectOrDisconnect(serial, connectDeviceMessage, 14);
    if(!res)
    {
        qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接成功，物理地址已分配";
        error->showWarningMsg(this, "点对点连接成功，物理地址已分配");
        knxSerial->knxConnectOrDisconnect(serial, disConnectMessage, 14);
        return;
    }
    
    //对处于编程模式的设备写物理地址
    uchar writeDevicePAMsg[17] = {0x00};
    knxSerial->knxGetWritePAByBroadcastMethod(writeDevicePAMsg, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow);
    knxSerial->knxDebugUcharMessage(writeDevicePAMsg, 17);
    res = knxSerial->knxWritePAByBroadcastMethod(serial, writeDevicePAMsg, 17);
    if(res < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"对处于编程模式的设备写物理地址失败";
        error->showCriticalMsg(this, "对处于编程模式的设备写物理地址失败");
        return;
    }
    
    //进行点对点连接判断物理地址是否写入成功
    res = knxSerial->knxConnectOrDisconnect(serial, connectDeviceMessage, 14);
    if(res < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接不成功，物理地址写入失败";
        error->showCriticalMsg(this, "点对点连接不成功，物理地址写入失败");
        return ;
    }
    
    qInfo()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接成功，物理地址写入成功";
    error->showInfoMsg(this, "点对点连接成功，物理地址写入成功");
    
    //断开点对点连接
    knxSerial->knxConnectOrDisconnect(serial, disConnectMessage, 14);
}

void ConfigDeviceDlg::readPAWhenDeviceProMode()
{
    //广播读取处于编程模式的设备的物理地址
    uchar readDeviceMsg[15] = {0x00};
    knxSerial->knxGetReadDevicePAByBroadcastMethod(readDeviceMsg, MC_PA_BYTE1, MC_PA_BYTE2);
    knxSerial->knxDebugUcharMessage(readDeviceMsg, 15);
    int PA = knxSerial->knxReadDevicePAByBroadcastMethod(serial, readDeviceMsg, 15);
    if(PA < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"读取物理地址失败";
        error->showCriticalMsg(this, "读取处于编程模式的设备的物理地址失败");
        return;
    }
    
    //转换为*.*.*形式
    PAStr = knxSerial->knxSetPAToString(PAStr, PA);
    
    ui->showPAlineEdit->setText(PAStr);
}

void ConfigDeviceDlg::downloadPA()
{
    if(ui->onecheckBox->checkState() == Qt::Checked)
    {
        downloadPABySN();
    }
    if(ui->twocheckBox->checkState() == Qt::Checked)
    {
        downloadPAWhenProMode();
    }
}

void ConfigDeviceDlg::downloadData()
{    
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"开始进行数据写入";
    //设置进度条显示窗口
    QProgressDialog process;
    process.setWindowModality(Qt::WindowModal);
    process.setWindowTitle(QObject::tr("配置数据下发"));
    process.setLabelText("下载中...");
    process.setRange(0,10);
    process.setMinimumDuration(1000);
    for(int i = 0;i < 9;i++)
    {
        if(1 == i)
        {
            //进行点对点连接
            uchar connectMessage[14] = {0x00};
            knxSerial->knxGetConOrDisMessage(connectMessage, MC_PA_BYTE1,MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, 0);
            int ret = knxSerial->knxConnectOrDisconnect(serial, connectMessage, 14);
            if(ret < 0)
            {
                qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接失败";
                error->showCriticalMsg(this, "点对点连接失败");
                return;
            }
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接成功";
        }
        if(2 == i)
        {
            //判断设备型号和是否处于编程模式
            int ret = judgeDeviceTypeAndMode();
            if(ret < 0)
            {
                qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"点对点连接失败";
                error->showCriticalMsg(this, "判断设备型号和是否处于编程模式不通过");
                return;
            }
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"判断设备型号和是否处于编程模式通过";
        }
        if(3 == i)
        {
            if(sendInterfaceObjectTableData() < 0)
            {
                qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发接口对象表失败";
                error->showCriticalMsg(this, "下发接口对象表失败");
                return;
            }
        }
        if(4 == i)
        {
            if(sendCOMMObjectTableData() < 0)
            {
                qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发通讯对象表失败";
                error->showCriticalMsg(this, "下发通讯对象表失败");
                return;
            }
        }
        if(5 == i)
        {
            if(sendAddressTableData() < 0)
            {
                qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发地址表失败";
                error->showCriticalMsg(this, "下发地址表失败");
                return;
            }
        }
        if(6 == i)
        {
            if(sendRelationTableData() < 0)
            {
                qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发关联表失败";
                error->showCriticalMsg(this, "下发关联表失败");
                return;
            }
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"写四张表数据完成";
        }
        if(7 == i)
        {
            //断开点对点连接
            uchar disConnectMessage[14] = {0x00};
            knxSerial->knxGetConOrDisMessage(disConnectMessage, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow,1);
            int ret = knxSerial->knxConnectOrDisconnect(serial, disConnectMessage, 14);
            if(ret < 0)
            {
                qWarning()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"断开点对点连接失败";
                error->showWarningMsg(this, "断开点对点连接失败");
                return;
            }
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"断开点对点连接成功";
        }
        if(8 == i)
        {
            //重启设备
            uchar getRestartMessage[15] = {0x00};
            knxSerial->knxGetRestartMessage(getRestartMessage, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow);
            int ret = knxSerial->knxRestart(serial, getRestartMessage, 15);
            if(ret < 0)
            {
                qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"数据写入完成后重启失败";
                error->showCriticalMsg(this, "数据写入完成后重启失败");
                return;
            }
            qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"数据写入完成后重启成功";
        }
        for(int j = 0;j < 30000;j++)
            process.setValue(i);
    }
    
    qInfo()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送配置数据成功";
    error->showInfoMsg(this, "发送数据成功");
}

int ConfigDeviceDlg::judgeDeviceTypeAndMode()
{
    return 0;
}

int ConfigDeviceDlg::sendInterfaceObjectTableData()
{
    //发送接口对象表数据
    uchar interfaceObjectTableData[MAX_DATA_LEN] = {0};
    
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发接口对象表数据中";
    //获取设备id
    int deviceID = selectDeviceIDByPA(PAStr);
    if(deviceID < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取设备id失败";
        error->showCriticalMsg(this, "获取设备id失败");
        return -1;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备id："<<deviceID;
    
    //获取数据长度
    int dataLen = selectInterfaceObjectDataLenByDeviceID(deviceID);
    if(dataLen < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取数据长度失败";
        error->showCriticalMsg(this, "获取数据长度失败");
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"dataLen:"<<dataLen;
    
    //获取起始eeprom地址
    int eepromAddressBegin = selectInterfaceObjectTableEepromAddressBegin(deviceID);
    if(eepromAddressBegin < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取起始eeprom地址失败";
        error->showCriticalMsg(this, "获取起始eeprom地址失败");
        return -3;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"起始eeprom地址："<<eepromAddressBegin;
    
    //获取接口对象表数据
    if(!selectInterfaceObjectDataByDeviceID(deviceID, interfaceObjectTableData))
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取接口对象表数据失败";
        error->showCriticalMsg(this, "获取接口对象表数据失败");
        return -4;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取接口对象表数据成功";
    
    //发送接口对象表数据
    if(knxSerial->knxSendTableUseStandardFrame(serial, interfaceObjectTableData, dataLen, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, eepromAddressBegin) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送接口对象表数据失败";
        error->showCriticalMsg(this, "发送接口对象表数据失败");
        return -5;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送接口对象表成功";

    return 0;
}

int ConfigDeviceDlg::sendCOMMObjectTableData()
{
    //发送通讯对象表数据
    uchar commObjectTableData[MAX_DATA_LEN] = {0};
    
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发通讯对象表数据中";
    //获取设备id
    int deviceID = selectDeviceIDByPA(PAStr);
    if(deviceID < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取设备id失败";
        error->showCriticalMsg(this, "获取设备id失败");
        return -1;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备id："<<deviceID;
    
    //获取数据长度
    int dataLen = selectCommObjectDataLenByDeviceID(deviceID);
    if(dataLen < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取数据长度失败";
        error->showCriticalMsg(this, "获取数据长度失败");
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"dataLen:"<<dataLen;
    
    //获取起始eeprom地址
    int eepromAddressBegin = selectCommObjectTableEepromAddressBegin(deviceID);
    if(eepromAddressBegin < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取起始eeprom地址失败";
        error->showCriticalMsg(this, "获取起始eeprom地址失败");
        return -3;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"起始eeprom地址："<<eepromAddressBegin;
    
    //获取通讯对象表数据
    if(!selectCommObjectDataByDeviceID(deviceID, commObjectTableData))
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取通讯对象表数据失败";
        error->showCriticalMsg(this, "获取通讯对象表数据失败");
        return -4;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取通讯对象表数据成功";
    
    //发送通讯对象表数据
    if(knxSerial->knxSendTableUseStandardFrame(serial, commObjectTableData, dataLen, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, eepromAddressBegin) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送通讯对象表数据失败";
        error->showCriticalMsg(this, "发送通讯对象表数据失败");
        return -5;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送通讯对象表成功";

    return 0;
}

int ConfigDeviceDlg::sendAddressTableData()
{
    //发送地址表数据
    uchar addressTableData[MAX_DATA_LEN] = {0};
    
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发地址表数据中";
    //获取设备id
    int deviceID = selectDeviceIDByPA(PAStr);
    if(deviceID < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取设备id失败";
        error->showCriticalMsg(this, "获取设备id失败");
        return -1;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备id："<<deviceID;
    
    //获取数据长度
    int dataLen = selectAddressDataLenByDeviceID(deviceID);
    if(dataLen < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取数据长度失败";
        error->showCriticalMsg(this, "获取数据长度失败");
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"dataLen:"<<dataLen;
    
    //获取起始eeprom地址
    int eepromAddressBegin = selectAddressTableEepromAddressBegin(deviceID);
    if(eepromAddressBegin < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取起始eeprom地址失败";
        error->showCriticalMsg(this, "获取起始eeprom地址失败");
        return -3;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"起始eeprom地址："<<eepromAddressBegin;
    
    //获取地址表数据
    if(!selectAddressDataByDeviceID(deviceID, addressTableData))
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取地址表数据失败";
        error->showCriticalMsg(this, "获取地址表数据失败");
        return -4;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取地址表数据成功";
    
    //发送地址表数据
    if(knxSerial->knxSendTableUseStandardFrame(serial, addressTableData, dataLen, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, eepromAddressBegin) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送地址表数据失败";
        error->showCriticalMsg(this, "发送地址表数据失败");
        return -5;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送地址表成功";

    return 0;
}

int ConfigDeviceDlg::sendRelationTableData()
{
    //发送关联表数据
    uchar relationTableData[MAX_DATA_LEN] = {0};
    
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"下发关联表数据中";
    //获取设备id
    int deviceID = selectDeviceIDByPA(PAStr);
    if(deviceID < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取设备id失败";
        error->showCriticalMsg(this, "获取设备id失败");
        return -1;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"设备id："<<deviceID;
    
    //获取数据长度
    int dataLen = selectRelationDataLenByDeviceID(deviceID);
    if(dataLen < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取数据长度失败";
        error->showCriticalMsg(this, "获取数据长度失败");
        return -2;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"dataLen:"<<dataLen;
    
    //获取起始eeprom地址
    int eepromAddressBegin = selectRelationTableEepromAddressBegin(deviceID);
    if(eepromAddressBegin < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取起始eeprom地址失败";
        error->showCriticalMsg(this, "获取起始eeprom地址失败");
        return -3;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"起始eeprom地址："<<eepromAddressBegin;
    
    //获取关联表数据
    if(!selectRelationDataByDeviceID(deviceID, relationTableData))
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取关联表数据失败";
        error->showCriticalMsg(this, "获取关联表数据失败");
        return -4;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"获取关联表数据成功";
    
    //发送关联表数据
    if(knxSerial->knxSendTableUseStandardFrame(serial, relationTableData, dataLen, MC_PA_BYTE1, MC_PA_BYTE2, devicePAByteHigh, devicePAByteLow, eepromAddressBegin) < 0)
    {
        qCritical()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送关联表数据失败";
        error->showCriticalMsg(this, "发送关联表数据失败");
        return -5;
    }
    qDebug()<<"file:"<<__FILE__<<"line:"<<__LINE__<<"发送关联表成功";

    return 0;
}
